package com.tiancheng.trade.commom.core.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import org.apache.commons.codec.binary.Base64;
import org.springframework.util.CollectionUtils;

import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.MessageFormat;
import java.util.*;

public class SignUtil {
    
	private static final String MAC_NAME = "HmacSHA1";
	
	public static final String ENCODING = "UTF-8";

    public static String generateAppKey(){
        final String uuidString = UUID.randomUUID().toString();
        return hashString(uuidString);
    }
    private static String hashString(String input) {
        try {
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            byte[] encodedHash = digest.digest(input.getBytes(StandardCharsets.UTF_8));
            return bytesToHex(encodedHash);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
    }

    private static String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            String hex = Integer.toHexString(0xff & b);
            if (hex.length() == 1) sb.append('0');
            sb.append(hex);
        }
        return sb.toString();
    }

    public static String HmacSHA1Encrypt(String encryptText, String encryptKey) throws Exception{
        byte[] data = encryptKey.getBytes( ENCODING );
        SecretKey secretKey = new SecretKeySpec( data, MAC_NAME );
        Mac mac = Mac.getInstance( MAC_NAME );
        mac.init(secretKey);
        byte[] text = encryptText.getBytes( ENCODING );
        byte[] digest = mac.doFinal( text );
        return new String(Base64.encodeBase64(digest));
	}
    
    public static String createSignStr(Map<String, Object> parameters) {
    	TreeMap<String, Object> treeMap = new TreeMap<>(parameters);
		StringBuffer strBuffer = new StringBuffer();
		treeMap.entrySet().forEach(i -> {
			if (i.getValue() == null) {
				return;
			}
			try {
				strBuffer.append(i.getKey()).append("=").append(URLEncoder.encode(String.valueOf(i.getValue()), "utf-8")).append("&");
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}
		});
		return strBuffer.substring(0, strBuffer.length() - 1);
    }
    
    public static SortedMap buildMap(JSONObject jsonObject) {
    	SortedMap map = new TreeMap();
//    	String jsonStr = JSONObject.toJSONString(object);
//    	JSONObject jsonObject = JSONObject.parseObject(jsonStr);
    	for (Map.Entry<String, Object> entry : jsonObject.entrySet()) {
//    		if(entry.getKey().equals("data")) {
//    			JSONObject data = (JSONObject)entry.getValue();
//    			for (Map.Entry<String, Object> dataEntry : data.entrySet()) {
//    				map.put(dataEntry.getKey(), dataEntry.getValue());
//    			}
//    		}else {
    			map.put(entry.getKey(), entry.getValue());
//    		}
        }
		return map;
	}
    
    public static String createSign(Object object) {
//    	String jsonStr = JSONObject.toJSONString(object,SerializerFeature.NotWriteDefaultValue);
    	String jsonStr = JSONObject.toJSONString(object);
    	JSONObject jsonObject = JSONObject.parseObject(jsonStr);
    	SortedMap map = buildMap(jsonObject);
    	String dddd = "";
    	try {
			dddd = genSignStr(map);
		} catch (Exception e) {
			e.printStackTrace();
		}
    	return dddd;
    }

    private static String getURLEncoderString(Object str) {
        String result = "";
        if (null == str) {
            return result;
        }
        try {
            result = URLEncoder.encode(str.toString(), "UTF-8")
                    // 腾云签名计算使用 rawurlencode，使用主动替换 '+'
                    .replaceAll("\\+", "%20").replaceAll("\\*", "%2A");
        } catch (Exception ex) {
        }
        return result;
    }
    
    private static String genSignStr(SortedMap<String, Object> msgBodyMap) throws Exception {
        if (CollectionUtils.isEmpty(msgBodyMap)) {
        }

        StringBuilder str = new StringBuilder();
        for (String key : msgBodyMap.keySet()) {
            if ("sign".equals(key)) {
                continue;
            }
            Object val = msgBodyMap.get(key);
            if (Objects.isNull(val)) {
                str.append(MessageFormat.format("{0}=&", getURLEncoderString(key)));
            } else if (val instanceof JSONObject) {
                SortedMap<String, Object> msgBody = new TreeMap<>();
                String xx = JSON.toJSONString(val);
                msgBody = JSON.parseObject(JSON.toJSONString(val, SerializerFeature.WriteMapNullValue), msgBody.getClass());
                str.append(MessageFormat.format("{0}={1}&", key, genSignStr(msgBody)));
            } else if (!(val instanceof JSONArray)) {
                str.append(MessageFormat.format("{0}={1}&", getURLEncoderString(key), getURLEncoderString(val.toString())));
            }
        }
        String signStr = str.toString();
        signStr = signStr.substring(0, signStr.length() - 1);
        return signStr;
    }

}
